package com.sunrise.relatorios.servico;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;

import javax.annotation.Resource;

import lombok.Getter;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sunrise.crm.repositorio.iface.UsuarioDao;
import com.sunrise.financeiro.repositorio.iface.CategoriaFinanceiraDao;
import com.sunrise.financeiro.repositorio.iface.ContaDao;
import com.sunrise.financeiro.repositorio.iface.DespesaDao;
import com.sunrise.financeiro.repositorio.iface.GrupoCategoriaFinanceiraDao;
import com.sunrise.financeiro.repositorio.iface.ReceitaDao;
import com.sunrise.financeiro.repositorio.iface.RecorrenciaDao;
import com.sunrise.generico.entidade.CategoriaFinanceira;
import com.sunrise.generico.entidade.Conta;
import com.sunrise.generico.entidade.GrupoCategoriaFinanceira;
import com.sunrise.generico.entidade.Usuario;
import com.sunrise.generico.enums.TipoMovimentacaoFinanceira;
import com.sunrise.generico.to.FluxoFinanceiroTO;
import com.sunrise.generico.to.GrupoRelatorioTO;
import com.sunrise.generico.to.RelatorioTO;
import com.sunrise.relatorios.visao.GerarRelatorioForm;

@Service
@Transactional(readOnly = true)
public class GerarRelatorioService {

	@Resource(name = "categoriaFinanceiraDaoImpl")
	@Getter
	private CategoriaFinanceiraDao categoriaFinanceiraDAO;

	@Resource(name = "grupoCategoriaFinanceiraDaoImpl")
	@Getter
	private GrupoCategoriaFinanceiraDao grupoCategoriaFinanceiraDAO;

	@Resource(name = "contaDaoImpl")
	@Getter
	private ContaDao contaDAO;

	@Resource(name = "usuarioDaoImpl")
	@Getter
	private UsuarioDao usuarioDAO;

	@Resource(name = "despesaDaoImpl")
	@Getter
	private DespesaDao despesaDAO;
	
	@Resource(name = "recorrenciaDaoImpl")
	@Getter
	private RecorrenciaDao recorrenciaDAO;


	@Resource(name = "receitaDaoImpl")
	@Getter
	private ReceitaDao receitaDAO;

	public Usuario buscarUsuarioPorUsername(String name) {
		return getUsuarioDAO().buscarPorUsername(name);
	}

	public Collection<Conta> listarContasPorUsuario(Usuario usuario) {
		return getContaDAO().listarPorUsuario(usuario);
	}

	public void gerarRelatorioFluxoCaixa(GerarRelatorioForm formulario) {
		Collection<GrupoCategoriaFinanceira> grupos = getGrupoCategoriaFinanceiraDAO().listarOrdenado();
		
		formulario.setFluxoDespesa(new FluxoFinanceiroTO());
		formulario.setFluxoReceita(new FluxoFinanceiroTO());
		formulario.getFluxoDespesa().setValor(new BigDecimal(0));
		formulario.getFluxoReceita().setValor(new BigDecimal(0));
		formulario.getFluxoDespesa().setValores(new ArrayList<GrupoRelatorioTO>());
		formulario.getFluxoReceita().setValores(new ArrayList<GrupoRelatorioTO>());
		
		
		for (GrupoCategoriaFinanceira grupo : grupos) {
			Boolean grupoValido = false;

			GrupoRelatorioTO grupoRelatorio = new GrupoRelatorioTO();
			grupoRelatorio.setValores(new ArrayList<RelatorioTO>());
			grupoRelatorio.setNome(grupo.getNome());
			grupoRelatorio.setValor(new BigDecimal(0));
			Collection<CategoriaFinanceira> categorias = getCategoriaFinanceiraDAO().listarPorGrupo(grupo.getId());

			for (CategoriaFinanceira categoria : categorias) {
				RelatorioTO itemGrupo = new RelatorioTO();
				itemGrupo.setNome(categoria.getNome());
				itemGrupo.setValor(new BigDecimal(0));

				if (grupo.getTipoMovimentacaoFinanceira().equals(TipoMovimentacaoFinanceira.RECEITA)) {
					BigDecimal receita = getReceitaDAO().buscarSomaPorFiltroSemRecorrencia(formulario.getDataInicio(),
							formulario.getDataFim(), formulario.getIdConta(), categoria.getId());
					
					BigDecimal receitasRecorrentes = getRecorrenciaDAO().buscarSomaReceitaPorFiltro(formulario.getDataInicio(),
							formulario.getDataFim(), formulario.getIdConta(), categoria.getId());
					
					if (receita != null) {
						formulario.getFluxoReceita().setValor(formulario.getFluxoReceita().getValor().add(receita));
						itemGrupo.setValor(receita);
						grupoRelatorio.setValor(grupoRelatorio.getValor().add(receita));
					}
					

					if (receitasRecorrentes != null) {
						formulario.getFluxoReceita().setValor(formulario.getFluxoReceita().getValor().add(receitasRecorrentes));
						itemGrupo.setValor(receitasRecorrentes);
						grupoRelatorio.setValor(grupoRelatorio.getValor().add(receitasRecorrentes));
					}

				} else {
					BigDecimal despesa = getDespesaDAO().buscarSomaPorFiltroSemRecorrencia(formulario.getDataInicio(),
							formulario.getDataFim(), formulario.getIdConta(), categoria.getId());
					
					BigDecimal despesasRecorrentes = getRecorrenciaDAO().buscarSomaDespesaPorFiltro(formulario.getDataInicio(),
							formulario.getDataFim(), formulario.getIdConta(), categoria.getId());

					if (despesa != null) {
						formulario.getFluxoDespesa().setValor(formulario.getFluxoDespesa().getValor().add(despesa));
						itemGrupo.setValor(despesa);
						grupoRelatorio.setValor(grupoRelatorio.getValor().add(despesa));
					}
					
					
					if(despesasRecorrentes != null){
						formulario.getFluxoDespesa().setValor(formulario.getFluxoDespesa().getValor().add(despesasRecorrentes));
						itemGrupo.setValor(despesasRecorrentes);
						grupoRelatorio.setValor(grupoRelatorio.getValor().add(despesasRecorrentes));
					}
					

				}
				if(itemGrupo.getValor().compareTo(new BigDecimal(0)) > 0 || !formulario.getSomenteCategorias()){
					grupoRelatorio.getValores().add(itemGrupo);
					grupoValido = true;
				}
			}

			if (grupo.getTipoMovimentacaoFinanceira().equals(TipoMovimentacaoFinanceira.RECEITA) && grupoValido) {
				formulario.getFluxoReceita().getValores().add(grupoRelatorio);
			} else if(grupoValido){
				formulario.getFluxoDespesa().getValores().add(grupoRelatorio);
			}
		}

	}

}